<?php
class templatecpl {
	
	/**
	 * 编译模板
	 *
	 * @param $module	模块名称
	 * @param $template	模板文件名
	 * @param $istag	是否为标签模板
	 * @return unknown
	 */
	public function template_compile($tplfile,$cpledfile) {
		$content = @file_get_contents ( $tplfile );
		$dir = dirname($cpledfile);
	    if(!is_dir($dir)) {
			if(!mkdir($dir, 0777, true)){
				exit('error:tpl failed');
			}
	    }
		$content = $this->template_parse($content);
		$strlen = file_put_contents ( $cpledfile, $content );
		chmod ( $cpledfile, 0777 );
	}
	
	/**
	 * 更新模板缓存
	 *
	 * @param $tplfile	模板原文件路径
	 * @param $compiledtplfile	编译完成后，写入文件名
	 * @return $strlen 长度
	 */
	public function template_refresh($tplfile, $compiledtplfile) {
		$str = @file_get_contents ($tplfile);
		$str = $this->template_parse ($str);
		$strlen = file_put_contents ($compiledtplfile, $str );
		chmod ($compiledtplfile, 0777);
		return $strlen;
	}
	

	/**
	 * 解析模板
	 *
	 * @param $str	模板内容
	 * @return ture
	 */
	public function template_parse($str) {
		$str = preg_replace('/\{template\s+(.+)\}/', "<?php include template(\\1); ?>", $str );
		$str = preg_replace('/\{include\s+(.+)\}/', "<?php include \\1; ?>", $str );
		$str = preg_replace('/\{php\s+(.+)\}/', "<?php \\1?>", $str );
		$str = preg_replace('/\{if\s+(.+?)\}/', "<?php if(\\1) { ?>", $str );
		$str = preg_replace('/\{else\}/', "<?php } else { ?>", $str );
		$str = preg_replace('/\{elseif\s+(.+?)\}/', "<?php } elseif (\\1) { ?>", $str );
		$str = preg_replace('/\{\/if\}/', '<?php } ?>', $str );
		//for 循环
		$str = preg_replace('/\{for\s+(.+?)\}/',"<?php for(\\1) { ?>",$str);
		$str = preg_replace('/\{\/for\}/', '<?php } ?>',$str);
		//++ --
		$str = preg_replace('/\{\+\+(.+?)\}/', "<?php ++\\1; ?>",$str);
		$str = preg_replace('/\{\-\-(.+?)\}/', "<?php ++\\1; ?>",$str);
		$str = preg_replace('/\{(.+?)\+\+\}/', "<?php \\1++; ?>",$str);
		$str = preg_replace('/\{(.+?)\-\-\}/',"<?php \\1--; ?>",$str);
		$str = preg_replace('/\{loop\s+(\S+)\s+(\S+)\}/', "<?php \$n=1;if(is_array(\\1)) foreach(\\1 AS \\2) { ?>", $str );
		$str = preg_replace('/\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}/', "<?php \$n=1; if(is_array(\\1)) foreach(\\1 AS \\2 => \\3) { ?>", $str );
		$str = preg_replace('/\{\/loop\}/', "<?php \$n++;}unset(\$n); ?>", $str );
		$str = preg_replace("/\\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\\(([^{}]*)\\))\\}/", "<?php echo \\1;?>", $str );
		$str = preg_replace("/\\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\\(([^{}]*)\\))\\}/", "<?php echo \\1;?>", $str );
		$str = preg_replace("/\\{(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\\}/", "<?php echo \\1;?>", $str );
		$str = preg_replace("/\\{(\\$[a-zA-Z0-9_\\[\\]\\'\"\$\x7f-\xff]+)\\}/es", "\$this->addquote('<?php echo \\1;?>')",$str);
		$str = preg_replace("/\\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\\}/s", "<?php echo \\1;?>", $str );
		$str = preg_replace("/\\{pc:(\\w+)\\s+([^}]+)\\}/ie", "self::pc_tag('$1','$2', '$0')", $str);
		$str = preg_replace('/\{\/pc\}/ie', "self::end_pc_tag()", $str);
		$str = "<?php defined('IN_APP') or exit('No permission resources.'); ?>" . $str;
		return $str;
	}

	/**
	 * 转义 // 为 /
	 *
	 * @param $var	转义的字符
	 * @return 转义后的字符
	 */
	public function addquote($var) {
		return str_replace ( "\\\"", "\"", preg_replace ( "/\\[([a-zA-Z0-9_\\-\\.\x7f-\xff]+)\\]/s", "['\\1']", $var ) );
	}
	
	/**
	 * 解析PC标签
	 * @param string $op 操作方式
	 * @param string $data 参数
	 * @param string $html 匹配到的所有的HTML代码
	 */
	public static function pc_tag($op, $data, $html) {
		preg_match_all("/([a-z]+)\\=[\"]?([^\"]+)[\"]?/i", stripslashes($data), $matches, PREG_SET_ORDER);
		//特殊的属性
		$arr = array('action','num','cache','page', 'pagesize', 'urlrule', 'return', 'start');
		
		//特殊化的不再支持
		//$tools = array('json', 'xml', 'block', 'get'); 
		$datas = array();
		$tag_id = md5(stripslashes($html));
		
		//可视化条件//liaozc:foreach这些代码没有用了
		$str_datas = 'op='.$op.'&tag_md5='.$tag_id;
		foreach ($matches as $v) {
			$str_datas .= $str_datas ? "&$v[1]=".($op == 'block' && strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2])) : "$v[1]=".(strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2]));
			if(in_array($v[1], $arr)) {
				$$v[1] = $v[2];
				continue;
			}
			$datas[$v[1]] = $v[2];
		}
		$str = '';
		
		//处理特殊的 标签
		if($op=='block'){
			$str = "echo hblock('".$datas['pos']."');" ;
		}else{
			//特殊的属性
			$num = isset($num) && intval($num) ? intval($num) : 20;
			$cache = isset($cache) && intval($cache) ? intval($cache) : 0;
			$return = isset($return) && trim($return) ? trim($return) : 'data';
			if (!isset($urlrule)) $urlrule = '';
			if (!isset($action) || empty($action)) return false;
	
			$str .= '$'.$op.'_tag = core::loadtag("'.$op.'");if (method_exists($'.$op.'_tag, \''.$action.'\')) {';	
			if (isset($start) && intval($start)) {
				$datas['limit'] = intval($start).','.$num;
			} else {
				$datas['limit'] = $num;
			}
			if (isset($page)) {
				$str .= '$pagesize = '.$num.';';
				$str .= '$page = intval('.$page.') ? intval('.$page.') : 1;if($page<=0){$page=1;}';
				$str .= '$offset = ($page - 1) * $pagesize;';
				$datas['limit'] = '$offset.",".$pagesize';
				$datas['action'] = $action;
				$str .= '$'.$op.'_total = $'.$op.'_tag->count('.self::arr_to_html($datas).');';
				$str .= '$pages = pages($'.$op.'_total, $page, $pagesize, $urlrule);';
			}
			$str .= '$'.$return.' = $'.$op.'_tag->'.$action.'('.self::arr_to_html($datas).');';
			$str .= '}';
		}

		return "<?php $str ?>";
	}
	
	/**
	 * PC标签结束
	 */
	static private function end_pc_tag() {
		return ' ';
		/*return '<?php if(defined(\'IN_ADMIN\') && !defined(\'HTML\')) {echo \'</div>\';}?>';*/
	}
	
	/**
	 * 转换数据为HTML代码
	 * @param array $data 数组
	 */
	private static function arr_to_html($data) {
		if (is_array($data)) {
			$str = 'array(';
			foreach ($data as $key=>$val) {
				if (is_array($val)) {
					$str .= "'$key'=>".self::arr_to_html($val).",";
				} else {
					if (strpos($val, '$')===0) {
						$str .= "'$key'=>$val,";
					} else {
						$str .= "'$key'=>'".fx_utl::addslashes($val)."',";
					}
				}
			}
			return $str.')';
		}
		return false;
	}
}